package com.zwh.minio;

import com.zwh.minio.multipart.MultipartUploadTaskVo;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.ListPartsResponse;
import io.minio.MinioClient;
import io.minio.http.Method;
import io.minio.messages.Part;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author zwh
 * @date 2024-3-25 17:41
 */
@Slf4j
@AllArgsConstructor
@Service
public class MinIOService {
    private final MinioClient minioClient;
    private final CustomMinioClient customMinioClient;

    /**
     * 原文链接：【https://blog.csdn.net/Tuine/article/details/113996848】
     * 向minio发起:初始化分片信息,返回各个分片url上传地址（前端自己调用接口将文件上传，上传完成后调用合并分片接口完成。）
     *
     * @param bucketName
     * @param objectName
     * @param totalPart
     * @return
     */
    public MultipartUploadTaskVo initMultiPartUpload(String bucketName, String objectName, int totalPart) {
        MultipartUploadTaskVo taskVo = new MultipartUploadTaskVo();
        taskVo.setUploadUrls(new ArrayList<>(totalPart));
        try {
            String uploadId = customMinioClient.initMultiPartUpload(bucketName, null, objectName, null, null);

            taskVo.setUploadId(uploadId);
            Map<String, String> reqParams = new HashMap<>();
            // reqParams.put("response-content-type", "application/json");
            reqParams.put("uploadId", uploadId);
            for (int i = 1; i <= totalPart; i++) {
                reqParams.put("partNumber", String.valueOf(i));
                String uploadUrl = customMinioClient
                    .getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.PUT).bucket(bucketName)
                        .object(objectName).expiry(1, TimeUnit.DAYS).extraQueryParams(reqParams).build());

                taskVo.getUploadUrls().add(new MultipartUploadTaskVo.UploadTaskItem(i, uploadUrl));
            }
        } catch (Exception e) {
            log.error("error: {}", e.getMessage(), e);
            return null;
        }
        return taskVo;
    }

    /**
     * 上传完成，发起分片信息合并请求
     *
     * @param bucketName
     * @param objectName
     * @param uploadId
     * @return
     */
    public boolean mergeMultipartUpload(String bucketName, String objectName, String uploadId) {
        try {
            Part[] parts = new Part[1000];
            // 此方法注意2020.02.04之前的minio服务端有bug
            ListPartsResponse partResult =
                customMinioClient.listMultipart(bucketName, null, objectName, 1000, 0, uploadId, null, null);
            int partNumber = 1;
            for (Part part : partResult.result().partList()) {
                parts[partNumber - 1] = new Part(partNumber, part.etag());
                partNumber++;
            }
            customMinioClient.mergeMultipartUpload(bucketName, null, objectName, uploadId, parts, null, null);
        } catch (Exception e) {
            log.error("error: {}", e.getMessage(), e);
            return false;
        }
        return true;
    }
}
